﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace XMLSchemaExtractor.Generator.XSDEntities
{
    class XsdElement : XsdObject
    {
        private string baseType;
        private bool isMixed;
        private List<XsdElement> children;
        private List<XsdAttribute> attributes;

        public XsdElement() : base()
        {
            this.baseType = "";
            this.isMixed = false;
            this.children = new List<XsdElement>();
            this.attributes = new List<XsdAttribute>();
        }

        public string BaseType
        {
            get { return baseType; }
            set { baseType = value; }
        }

        public bool IsMixed
        {
            get { return isMixed; }
            set { isMixed = value; }
        }

        public List<XsdElement> Children
        {
            get { return children; }
            set { children = value; }
        }

        public List<XsdAttribute> Attributes
        {
            get { return attributes; }
            set { attributes = value; }
        }

        public XsdElement AddChild(string name)
        {
            XsdElement c = FindChild(name);
            if (c == null)
            {
                c = new XsdElement();
                c.Name = name;
                children.Add(c);
            }
            c.Occurrence++;
            return c;
        }

        public XsdAttribute AddAttribute(string name)
        {
            XsdAttribute a = FindAttribute(name);
            if (a == null)
            {
                a = new XsdAttribute();
                a.Name = name;
                attributes.Add(a);
            }
            a.Occurrence++;
            return a;
        }

        public void CleanUp()
        {
            SetType();
            SetOccurrence();
            SetAttribute();
        }

        private void SetAttribute()
        {
            foreach (XsdAttribute attr in this.attributes)
            {
                if (attr.Occurrence == this.Occurrence)
                {
                    attr.IsRequired = true;
                }
            }
        }

        private void SetOccurrence()
        {
            switch (this.Type)
            {
                case "complexType":
                case "complexContent":
                case "emptyType":
                case "simpleContent":
                    break;
                default:
                    if (this.children.Count == 0)
                    {
                        this.Occurrence = 0;
                    }
                    break;
            }
        }

        private void SetType()
        {
            if (this.Type.Equals(""))
            {
                if (this.children.Count > 0)
                {
                    this.Type = "complexType";
                    this.isMixed = false;
                }
                else
                {
                    if (this.attributes.Count > 0)
                    {
                        this.Type = "complexContent";
                    }
                    else
                    {
                        this.Type = "emptyType";
                    }
                }
            }
            else
            {
                if (this.children.Count > 0)
                {
                    this.Type = "complexType";
                    this.isMixed = true;
                }
                else if (this.attributes.Count > 0)
                {
                    this.baseType = this.Type;
                    this.Type = "simpleContent";
                }
            }
            foreach (XsdElement child in this.children)
            {
                child.CleanUp();
            }
        }

        private XsdElement FindChild(string name)
        {
            return children.Find(child => child.Name.Equals(name));
        }

        private XsdAttribute FindAttribute(string name)
        {
            return attributes.Find(attr => attr.Name.Equals(name));
        }
    }
}
